﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ComponentModel;

namespace Panels
{
    public class MultiColumnStackPanel : Panel, INotifyPropertyChanged
    {
        #region Constructors

        public MultiColumnStackPanel()
        {
            Columns = 2;
        }

        #endregion Constructors
        #region INotifyPropertyChanged

        public event PropertyChangedEventHandler PropertyChanged;
        protected void NotifyPropertyChanged(string info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }

        #endregion INotifyPropertyChanged
        #region Properties

        public static readonly DependencyProperty ColumnsProperty = DependencyProperty.Register("Columns", typeof(int), typeof(MultiColumnStackPanel), new PropertyMetadata(OnColumnsPropertyChanged));
        public int Columns
        {
            get { return (int)GetValue(ColumnsProperty); }
            set { SetValue(ColumnsProperty, value); }
        }

        private static void OnColumnsPropertyChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            MultiColumnStackPanel panel = sender as MultiColumnStackPanel;
            if (panel != null)
            {
                if ((int)e.NewValue < 1)
                {
                    panel.Columns = 1;
                }

                panel.NotifyPropertyChanged("Columns");
            }
        }

        #endregion Properties

        protected override Size MeasureOverride(Size availableSize)
        {
            double maxWidth = 0.0;
            double totalHeight = 0.0;            
            Size rowSize = new Size();
            int column = 0;

            foreach (UIElement child in this.Children)
            {
                child.Measure(availableSize);
                Size childSize = child.DesiredSize;                

                rowSize.Height = Math.Max(childSize.Height, rowSize.Height);
                maxWidth = Math.Max(childSize.Width, maxWidth);

                column++;
                if (column >= Columns)
                {                    
                    totalHeight += rowSize.Height;
                    
                    rowSize.Height = 0.0;
                    column = 0;
                }
            }

            // Did we miss to register the last one?
            if (column % Columns != 0)
            {                
                totalHeight += rowSize.Height;
            }

            // Take the max width and multiply by the number of columns. 
            // This will give us equal sized columns.
            Size newSize = new Size(Math.Min(maxWidth * Columns, availableSize.Width), totalHeight);
            
            return newSize;
        }

        protected override Size ArrangeOverride(Size finalSize)
        {
            int column = 0;
            Point position = new Point(0.0, 0.0);
            Size rowSize = new Size();
            rowSize.Width = finalSize.Width / Columns;

            foreach (UIElement child in this.Children)
            {
                Size childSize = child.DesiredSize;

                childSize.Width = rowSize.Width;
                child.Arrange(new Rect(position.X, position.Y, childSize.Width, childSize.Height));

                position.X += childSize.Width;
                rowSize.Height = Math.Max(childSize.Height, rowSize.Height);
                column++;                

                if (column >= Columns)
                {
                    position.Y += rowSize.Height;

                    position.X = 0.0;
                    rowSize.Height = 0.0;
                    column = 0;
                }
            }

            return finalSize;
        }

    }
}
